package com.ooono.factorytest.auto;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.Vibrator;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import com.ooono.factorytest.R;
import com.ooono.factorytest.utils.SPUtils;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import mcs8.mdm.PolicyManager;

public class AutoTestItemActivity extends AppCompatActivity implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, SurfaceHolder.Callback {

    private static final String TAG = "AutoTestItemActivity";

    // 激光灯
    public static final Integer LAMP_TYPE_LASER_LED = 1;
    // 指示灯
    public static final Integer LAMP_TYPE_PILOT_LED = 2;
    // 闪光灯
    public static final Integer LAMP_TYPE_FLASH_LED = 3;
    // 爆闪灯
    public static final Integer LAMP_TYPE_STROBE_LED = 4;
    // 红外灯
    public static final Integer LAMP_TYPE_IR_LED = 5;
    // 三色灯
    public static final Integer LAMP_TYPE_TRICOLOR_LED = 6;
    private int currentTricolorLed = 1;

    private final List<Integer> lampList = new ArrayList<>();
    private int currentTestLampIndex = 0;
    private int laserLedTestTime = 0;
    private int pilotLedTestTime = 0;
    private int flashLedTestTime = 0;
    private int strobeLedTestTime = 0;
    private int irLedTestTime = 0;
    private int tricolorLedTestTime = 0;
    private Handler mLampHandler;
    private Runnable lampTestRunnable;

    private PowerManager.WakeLock mWakeLock = null;

    private boolean isTestSpeaker;
    private boolean isTestVibrator;
    private boolean isTestCamera;

    private long startTestTime;

    private int testDate;

    private TextView testTimeTv;
    private int testTime = 0;
    private TextureView cameraPreviewTv;
    private SurfaceView videoSv;
    private Size mPreviewSize;
    private final Object mCameraStateLock = new Object();
    private Handler mCameraHandler;
    private CameraCaptureSession mCameraCaptureSession;
    private CameraDevice mCameraDevice;
    private String[] cameraIdList;
    private int currentCameraId = 0;
    private CaptureRequest mCaptureRequest;
    private CaptureRequest.Builder mCaptureRequestBuilder;

    int cameraTestSwitch = 1;

    private MediaPlayer mMediaPlayer;
    private Vibrator vibrator;

    private final Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(@NonNull Message msg) {
            if (testTimeTv != null) {
                testTimeTv.setText((String) msg.obj);
            }
            return false;
        }
    });

    private final TimerTask mTimerTask = new TimerTask() {
        @Override
        public void run() {
            testTime = (int) ((SystemClock.elapsedRealtime() - startTestTime) / 1000);
            if (testTime >= (testDate * 60 * 60)) {
                // 结束测试，退出此界面
                finish();
            }
            if (isTestCamera && cameraTestSwitch % 10 == 0) {
                closeCamera();
                reopenCamera();
            }
            cameraTestSwitch++;
            String hh = new DecimalFormat("00").format(testTime / 3600);
            String mm = new DecimalFormat("00").format(testTime % 3600 / 60);
            String ss = new DecimalFormat("00").format(testTime % 60);
            String timeFormat = hh + ":" + mm + ":" + ss + ", 当前摄像头ID: " + currentCameraId;
            Message message = new Message();
            message.obj = timeFormat;
            mHandler.sendMessage(message);

            int currentTestLamp = lampList.get(currentTestLampIndex);
            if (currentTestLamp == LAMP_TYPE_LASER_LED) {
                laserLedTestTime ++;
            } else if (currentTestLamp == LAMP_TYPE_PILOT_LED) {
                pilotLedTestTime ++;
            } else if (currentTestLamp == LAMP_TYPE_FLASH_LED) {
                flashLedTestTime ++;
            } else if (currentTestLamp == LAMP_TYPE_STROBE_LED) {
                strobeLedTestTime ++;
            } else if (currentTestLamp == LAMP_TYPE_IR_LED) {
                irLedTestTime ++;
            } else if (currentTestLamp == LAMP_TYPE_TRICOLOR_LED) {
                tricolorLedTestTime++;
            }
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_auto_test_item);
        testTimeTv = findViewById(R.id.tv_test_time);
        cameraPreviewTv = findViewById(R.id.tv_camera_preview);
        videoSv = findViewById(R.id.sv_video_surfaceView);
        videoSv.setZOrderOnTop(false);
        videoSv.getHolder().addCallback(this);

        vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);

        Intent intent = getIntent();
        testDate = intent.getIntExtra("testDate", 0);
        isTestSpeaker = intent.getBooleanExtra("speaker", false);
        isTestVibrator = intent.getBooleanExtra("vibrator", false);
        isTestCamera = intent.getBooleanExtra("camera", false);

        if (isTestSpeaker) {
            startTestSpeaker();
        }
        if (isTestVibrator) {
            startTestVibrator();
        }
        if (isTestCamera) {
            startTestCamera();
        }

        if (intent.getBooleanExtra("laserLed", false)) {
            lampList.add(LAMP_TYPE_LASER_LED);
        }
        if (intent.getBooleanExtra("pilot", false)) {
            lampList.add(LAMP_TYPE_PILOT_LED);
        }
        if (intent.getBooleanExtra("flash", false)) {
            lampList.add(LAMP_TYPE_FLASH_LED);
        }
        if (intent.getBooleanExtra("strobeLed", false)) {
            lampList.add(LAMP_TYPE_STROBE_LED);
        }
        if (intent.getBooleanExtra("irLed", false)) {
            lampList.add(LAMP_TYPE_IR_LED);
        }
        if (intent.getBooleanExtra("tricolorLed", false)) {
            lampList.add(LAMP_TYPE_TRICOLOR_LED);
        }

        // 测试灯光线程
        lampTestRunnable = new Runnable() {
            @Override
            public void run() {
                closeAllLamp();
                int currentTestLamp = lampList.get(currentTestLampIndex);
                if (currentTestLamp == LAMP_TYPE_LASER_LED) {
                    PolicyManager.laserLightEnabled(true);
                } else if (currentTestLamp == LAMP_TYPE_PILOT_LED) {
                    PolicyManager.pilotLampOpen(true);
                } else if (currentTestLamp == LAMP_TYPE_FLASH_LED) {
                    PolicyManager.openFlash(true);
                } else if (currentTestLamp == LAMP_TYPE_STROBE_LED) {
                    PolicyManager.strobeLightEnable(true);
                } else if (currentTestLamp == LAMP_TYPE_IR_LED) {
                    PolicyManager.irLedEnable(true);
                } else if (currentTestLamp == LAMP_TYPE_TRICOLOR_LED) {
                    if (currentTricolorLed == 1) {
                        PolicyManager.redLightEnable(true);
                    } else if (currentTricolorLed == 2) {
                        PolicyManager.greenLightEnable(true);
                    } else if (currentTricolorLed == 3) {
                        PolicyManager.blueLightEnable(true);
                    }
                    currentTricolorLed ++;
                    if (currentTricolorLed > 3) {
                        currentTricolorLed = 1;
                    }
                }
                currentTestLampIndex++;
                if (currentTestLampIndex % lampList.size() == 0) {
                    currentTestLampIndex = 0;
                }
                mLampHandler.postDelayed(this, 5000);
            }
        };

        startTestTime = SystemClock.elapsedRealtime();
        new Timer("开启计时器").scheduleAtFixedRate(mTimerTask, 0, 1000L);
    }

    @Override
    protected void onResume() {
        super.onResume();
        HandlerThread mCameraThread = new HandlerThread("CameraThread");
        mCameraThread.start();
        mCameraHandler = new Handler(mCameraThread.getLooper());
        HandlerThread mLampThread = new HandlerThread("LampThread");
        mLampThread.start();
        mLampHandler = new Handler(mLampThread.getLooper());

        if (mWakeLock == null) {
            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, this.getClass().getCanonicalName());
            mWakeLock.acquire();
        }

        if (!lampList.isEmpty()) {
            // 开始测试灯光
            mLampHandler.post(lampTestRunnable);
        }
    }

    @Override
    protected void onPause() {
        Log.d("tag_ooono", ">>>-----:" + laserLedTestTime + ", " + pilotLedTestTime + ", " + flashLedTestTime + ", " + strobeLedTestTime + ", " + irLedTestTime
                +"," + tricolorLedTestTime);
        SPUtils.get(this).saveData("auto_laser_led", laserLedTestTime);
        SPUtils.get(this).saveData("auto_pilot", pilotLedTestTime);
        SPUtils.get(this).saveData("auto_flash", flashLedTestTime);
        SPUtils.get(this).saveData("auto_strobe_led", strobeLedTestTime);
        SPUtils.get(this).saveData("auto_ir_led", irLedTestTime);
        SPUtils.get(this).saveData("auto_tricolor_led", tricolorLedTestTime);


        Log.d("tag_ooono", ">>>-123----:" + SPUtils.get(this).getData("auto_laser_led", 0)
                + ", " + SPUtils.get(this).getData("auto_pilot", 0)
                + ", " + SPUtils.get(this).getData("auto_flash", 0)
                + ", " + SPUtils.get(this).getData("auto_strobe_led", 0)
                + ", " + SPUtils.get(this).getData("auto_ir_led", 0)
                +"," + SPUtils.get(this).getData("auto_tricolor_led", 0));

        super.onPause();
    }

    @Override
    protected void onStop() {
        Log.d("tag_ooono", "onStop...");
        stopTest();
        if (mWakeLock != null) {
            mWakeLock.release();
        }
        closeAllLamp();
        super.onStop();
    }

    private void stopTest() {
        Log.d(TAG, "stop test...");

        mTimerTask.cancel();
        stopTestSpeaker();
        stopTestVibrator();
        stopTestCamera();
        closeAllLamp();
        if (mLampHandler != null && lampTestRunnable != null) {
            mLampHandler.removeCallbacks(lampTestRunnable);
        }
    }

    private void startTestSpeaker() {
        stopTestSpeaker();
        AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.video);
        mMediaPlayer = new MediaPlayer();
        try {
            mMediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength());
            mMediaPlayer.setOnPreparedListener(this);
            mMediaPlayer.setOnCompletionListener(this);
        } catch (IOException ignored) {
        }
    }

    private void stopTestSpeaker() {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
        if (isTestSpeaker) {
            SPUtils.get(this).saveData("auto_speaker", testTime);
        }
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        mMediaPlayer.start();
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        mMediaPlayer.start();
    }

    private void startTestVibrator() {
        long[] patter = {0, 1000};
        vibrator.vibrate(patter, 0);
    }

    private void stopTestVibrator() {
        vibrator.cancel();
        if (isTestVibrator) {
            SPUtils.get(this).saveData("auto_vibrator", testTime);
        }
    }

    // 关闭所的灯
    private void closeAllLamp() {
        PolicyManager.laserLightEnabled(false);
        PolicyManager.pilotLampOpen(false);
        PolicyManager.openFlash(false);
        PolicyManager.strobeLightEnable(false);
        PolicyManager.irLedEnable(false);
        PolicyManager.redLightEnable(false);
        PolicyManager.greenLightEnable(false);
        PolicyManager.blueLightEnable(false);
    }

    private final TextureView.SurfaceTextureListener mTextureListener = new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
            configureTransform(width, height);
            openCamera();
        }

        @Override
        public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
            configureTransform(width, height);
            openCamera();
        }

        @Override
        public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
            synchronized (mCameraStateLock) {
                mPreviewSize = null;
            }
            return true;
        }

        @Override
        public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
        }
    };

    //选择sizeMap中大于并且最接近width和height的size
    private Size getOptimalSize(Size[] sizeMap, int width, int height) {
        List<Size> sizeList = new ArrayList<>();
        for (Size option : sizeMap) {
            if (width > height) {
                if (option.getWidth() > width && option.getHeight() > height) {
                    sizeList.add(option);
                }
            } else {
                if (option.getWidth() > height && option.getHeight() > width) {
                    sizeList.add(option);
                }
            }
        }
        if (!sizeList.isEmpty()) {
            return Collections.min(sizeList, (lhs, rhs) -> Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight()));
        }
        return sizeMap[0];
    }

    private void configureTransform(int width, int height) {
        // 获取摄像头的管理者CameraManager
        CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            cameraIdList = manager.getCameraIdList();
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIdList[currentCameraId]);
            //获取StreamConfigurationMap，它是管理摄像头支持的所有输出格式和尺寸
            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            assert map != null;
            //根据TextureView的尺寸设置预览尺寸
            mPreviewSize = getOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height);
        } catch (CameraAccessException ignored) {
        }
    }

    private void startPreview() {
        SurfaceTexture mSurfaceTexture = cameraPreviewTv.getSurfaceTexture();
        assert mSurfaceTexture != null;
        mSurfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
        Surface previewSurface = new Surface(mSurfaceTexture);
        try {
            mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            mCaptureRequestBuilder.addTarget(previewSurface);
            mCameraDevice.createCaptureSession(Collections.singletonList(previewSurface), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    try {
                        mCaptureRequest = mCaptureRequestBuilder.build();
                        mCameraCaptureSession = session;
                        mCameraCaptureSession.setRepeatingRequest(mCaptureRequest, null, mCameraHandler);
                    } catch (CameraAccessException ignored) {
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {

                }
            }, mCameraHandler);
        } catch (CameraAccessException ignored) {
        }
    }

    private void openCamera() {
        CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            manager.openCamera(cameraIdList[currentCameraId], new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice camera) {
                    mCameraDevice = camera;
                    startPreview();
                }

                @Override
                public void onDisconnected(@NonNull CameraDevice camera) {
                    camera.close();
                    mCameraDevice = null;
                }

                @Override
                public void onError(@NonNull CameraDevice camera, int error) {
                    camera.close();
                    mCameraDevice = null;
                }
            }, mCameraHandler);
        } catch (CameraAccessException ignored) {
        }
    }

    public void reopenCamera() {
        currentCameraId++;
        if (currentCameraId == cameraIdList.length) {
            currentCameraId = 0;
        }
        if (cameraPreviewTv.isAvailable()) {
            openCamera();
        } else {
            cameraPreviewTv.setSurfaceTextureListener(mTextureListener);
        }
    }

    private void startTestCamera() {
        if (cameraPreviewTv.isAvailable()) {
            openCamera();
        } else {
            cameraPreviewTv.setSurfaceTextureListener(mTextureListener);
        }
    }

    private void closeCamera() {
        synchronized (mCameraStateLock) {
            if (null != mCameraCaptureSession) {
                mCameraCaptureSession.close();
                mCameraCaptureSession = null;
            }
            if (null != mCameraDevice) {
                mCameraDevice.close();
                mCameraDevice = null;
            }
        }
    }

    private void stopTestCamera() {
        closeCamera();
        if (isTestCamera) {
            SPUtils.get(this).saveData("auto_camera", testTime);
        }
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
        Log.d(TAG, ">>>----------surfaceCreated-");
        if (mMediaPlayer != null) {
            Surface surface = surfaceHolder.getSurface();
            mMediaPlayer.setSurface(surface);
            mMediaPlayer.prepareAsync();
        }
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {

    }
}
